feat(telemetry): opt-out phone-home telemetry for the CLI and cli.deepgram.com#59
Merged
lukeocodes merged 2 commits intomainfrom May 7, 2026
Merged
feat(telemetry): opt-out phone-home telemetry for the CLI and cli.deepgram.com#59lukeocodes merged 2 commits intomainfrom
lukeocodes merged 2 commits intomainfrom
Conversation
Adds packages/deepctl-telemetry, a workspace-required Sentry client that ships with every install of deepctl. Errors phone home to the dx-cli Sentry project by default; users can opt out anywhere with: dg config set telemetry.enabled false (or DEEPCTL_TELEMETRY_DISABLED=1 for one-shot CI runs). Wired into src/deepctl/main.py before plugin loads, with a Click monkey-patch that appends a dim one-line notice to every --help output (group, subcommand, plugin command — anywhere Click formats help). The init/notice failure path is wrapped in try/except so a broken telemetry dep cannot crash the CLI. Hard-dep enforced via the root pyproject.toml dependencies list (same pattern as deepctl-core, deepctl-shared-utils, and every command package). Release-please config and test workflow updated. Default Sentry DSN points at the existing dx-cli project; override via DEEPCTL_TELEMETRY_DSN for forks or self-hosted Sentry.
Adds @sentry/astro to the marketing site, pointed at the same dx-cli Sentry project as the CLI itself. Sentry init runs from web/sentry.client.config.ts and skips if localStorage.dg_telemetry === 'off'. Footer toggle next to the copyright line lets visitors flip the flag and reload. State is rendered on every page load so the displayed value stays in sync with what's actually about to happen on the next visit.
There was a problem hiding this comment.
Pull request overview
Adds opt-out (default-on) Sentry-backed “phone-home” telemetry to both the Deepgram CLI and cli.deepgram.com, including a per-user toggle for the website and a --help footer notice for the CLI.
Changes:
- Introduces new
packages/deepctl-telemetrypackage to gate/init Sentry and append a telemetry notice to all Click help output. - Wires CLI startup to initialize telemetry early and extends
deepctl_coreconfig withtelemetry.enabled(defaulttrue). - Adds
@sentry/astroclient initialization for the website plus a localStorage-backed “Telemetry: on/off” toggle in the footer.
Reviewed changes
Copilot reviewed 18 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/pages/index.astro | Adds footer UI + client-side localStorage toggle to opt out of web telemetry. |
| web/sentry.client.config.ts | Initializes Sentry on the client only when not opted out via localStorage. |
| web/package.json | Adds @sentry/astro dependency. |
| web/package-lock.json | Locks Sentry (and transitive) dependencies. |
| web/astro.config.mjs | Registers Sentry Astro integration + source map upload configuration. |
| src/deepctl/main.py | Initializes CLI telemetry and installs Click help footer early in startup. |
| README.md | Documents new deepctl-telemetry workspace package. |
| pyproject.toml | Adds deepctl-telemetry as a root dependency + workspace source. |
| packages/deepctl-telemetry/tests/unit/test_telemetry.py | Unit tests for enablement logic and notice rendering. |
| packages/deepctl-telemetry/tests/unit/init.py | Test package marker. |
| packages/deepctl-telemetry/tests/init.py | Test package marker. |
| packages/deepctl-telemetry/src/deepctl_telemetry/notice.py | Implements Click get_help monkey-patch and notice rendering. |
| packages/deepctl-telemetry/src/deepctl_telemetry/client.py | Implements Sentry init + opt-out + event scrubbing. |
| packages/deepctl-telemetry/src/deepctl_telemetry/init.py | Public exports + version for telemetry package. |
| packages/deepctl-telemetry/README.md | Package-level documentation and usage notes. |
| packages/deepctl-telemetry/pyproject.toml | New package metadata and dependencies. |
| packages/deepctl-telemetry/CHANGELOG.md | Initializes changelog for release-please. |
| packages/deepctl-core/src/deepctl_core/config.py | Adds TelemetryConfig and DeepgramConfig.telemetry field. |
| .github/workflows/test.yml | Includes telemetry package tests in CI pytest invocation. |
| .github/release-please-config.json | Adds release-please configuration for telemetry package. |
| .github/.release-please-manifest.json | Adds telemetry package to release-please manifest. |
Files not reviewed (1)
- web/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+244
to
+246
| telemetry_config = Config() | ||
| init_telemetry(telemetry_config) | ||
| install_help_notice(telemetry_config) |
Comment on lines
+37
to
+45
| def init_telemetry(config: Config) -> bool: | ||
| """Initialize the Sentry SDK if telemetry is enabled. | ||
|
|
||
| Idempotent — safe to call multiple times. Returns whether init ran. | ||
| """ | ||
| global _initialized | ||
| if _initialized: | ||
| return True | ||
| if not is_enabled(config): |
Comment on lines
+1115
to
+1122
| const render = () => { | ||
| const off = localStorage.getItem(STORAGE_KEY) === 'off'; | ||
| stateEl.textContent = off ? 'off' : 'on'; | ||
| }; | ||
| toggleEl.addEventListener('click', () => { | ||
| const off = localStorage.getItem(STORAGE_KEY) === 'off'; | ||
| if (off) localStorage.removeItem(STORAGE_KEY); | ||
| else localStorage.setItem(STORAGE_KEY, 'off'); |
Comment on lines
+4
to
+7
| const optedOut = | ||
| typeof window !== 'undefined' && | ||
| window.localStorage?.getItem(STORAGE_KEY) === 'off'; | ||
|
|
Merged
lukeocodes
added a commit
that referenced
this pull request
May 8, 2026
…ME (#65) ## Summary Follow-up to #59. Three small fixes: 1. **Drop the web footer toggle** on `cli.deepgram.com`. The marketing site's Sentry init is non-opt-outable error/uptime monitoring — same model as every other public Deepgram web property. The toggle implied the visitor had agency over it, which they don't. 2. **Drop the `localStorage.dg_telemetry` gate** in `web/sentry.client.config.ts`. Without the toggle UI it was dead code, but it also let a power user disable site error monitoring via DevTools, which is not the intent. Sentry init is now unconditional for site visitors. 3. **Document CLI opt-out in the main README**. The three paths (`dg config set telemetry.enabled false`, `DEEPCTL_TELEMETRY_DISABLED=1`, `DEEPCTL_TELEMETRY_DSN`) were only discoverable via `--help` or source code. Now they live in a `## Telemetry` section right after `## Configuration` with what's collected, what's scrubbed, and where it lands. ## Why two telemetry surfaces, one opt-out story | Surface | Runs where | Opt-out | |---|---|---| | `cli.deepgram.com` Sentry | Visitor's browser, our marketing site | None — site error monitoring, owned by us | | `deepctl` Sentry | User's local machine, our installed binary | Three documented paths | The CLI phones home from the user's machine on user-side stack traces, so opt-out is mandatory and has to be discoverable. The website Sentry catches our own bugs in our own code on our own deployed site. Different consent model, different surface. ## Test plan - `web/sentry.client.config.ts` — Sentry init runs unconditionally; no `localStorage` reads - `web/src/pages/index.astro` — footer is just the copyright line; grep for `dg-tel` / `dg_telemetry` / `Telemetry: ` returns nothing - `README.md` — new `## Telemetry` section between `## Configuration` and `## Development` ## Related - #59 — original implementation (merged)
lukeocodes
added a commit
that referenced
this pull request
May 8, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>0.2.21</summary> ## [0.2.21](v0.2.20...v0.2.21) (2026-05-07) ### Features * delete .cursor directory ([2029795](2029795)) * **telemetry:** opt-out phone-home telemetry for the CLI and cli.deepgram.com ([#59](#59)) ([8e20b16](8e20b16)) </details> <details><summary>deepctl-core: 0.2.10</summary> ## [0.2.10](deepctl-core-v0.2.9...deepctl-core-v0.2.10) (2026-05-07) ### Features * **telemetry:** opt-out phone-home telemetry for the CLI and cli.deepgram.com ([#59](#59)) ([8e20b16](8e20b16)) </details> <details><summary>deepctl-telemetry: 0.0.2</summary> ## [0.0.2](deepctl-telemetry-v0.0.1...deepctl-telemetry-v0.0.2) (2026-05-07) ### Features * **telemetry:** opt-out phone-home telemetry for the CLI and cli.deepgram.com ([#59](#59)) ([8e20b16](8e20b16)) </details> <details><summary>deepctl-cmd-listen: 0.0.11</summary> ## [0.0.11](deepctl-cmd-listen-v0.0.10...deepctl-cmd-listen-v0.0.11) (2026-05-07) ### Documentation * fix dg listen examples and drop deprecated dg transcribe references ([#53](#53)) ([3a4e8a9](3a4e8a9)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phone-home telemetry for both the CLI and
cli.deepgram.com, both reporting into the existingdx-cliSentry project. Opt-out by default-on, configurable per user, can be killed entirely with one env var for CI runs.Sits alongside the new (disabled-pending-budget) Sentry uptime detector for
cli.deepgram.comso both sides of the project produce signal once budget lands.What changed
CLI (
packages/deepctl-telemetry)deepctl-telemetrywith three exports:init_telemetry(config)— lazysentry_sdk.initif telemetry is on, otherwise a no-op. Idempotent.is_enabled(config)— env override (DEEPCTL_TELEMETRY_DISABLED=1) wins, thenconfig.telemetry.enabled(defaultTrue)install_help_notice(config)— monkey-patchesclick.Command.get_helponce at startup so every--helpoutput (group, subcommand, plugin command, anywhere) ends with a dim one-line footerdx-cli. Override viaDEEPCTL_TELEMETRY_DSNfor forks/self-hosted Sentrybefore_sendhook scrubs request bodies, headers, cookies, email/IP/username fromuser, plussend_default_pii=False. Defense-in-depth — Sentry SDK does most of this but breadcrumbs/exception messages can still leak project IDs and file pathstraces_sample_rate=0andprofiles_sample_rate=0so we ship errors and breadcrumbs only, no perf dataCLI wiring
deepctl_core.config.DeepgramConfiggets atelemetry: TelemetryConfigfield withenabled: bool = Truesrc/deepctl/main.pycallsinit_telemetry()andinstall_help_notice()at the very top ofmain(), wrapped in a baretry/exceptso a broken telemetry dep can never crash the CLI itselfpyproject.tomland[tool.uv.sources]workspace member entry, same as every other shippable package.pip install deepctlpulls it in; you can't remove it without uninstalling the CLIWeb (
web/)@sentry/astrointegration inastro.config.mjs, init code inweb/sentry.client.config.tslocalStorage.dg_telemetry. If'off', Sentry never initializes that page loadTelemetry: on/offwith a toggle button that flips the flag and reloadstracesSampleRate/replaysSessionSampleRate/replaysOnErrorSampleRateall 0. Errors onlyNotice copy
When opted out:
Rendered with
click.style(..., dim=True)so it sits quietly under the help.Test plan
make check— ruff format/lint + mypy strict, all 115 source files cleanuv run pytest packages/deepctl-telemetry/tests— 5 passuv run dg --help— footer shows on telemetry onDEEPCTL_TELEMETRY_DISABLED=1 uv run dg --help— footer shows "off"uv run dg api --help— footer also shows on subcommand help (monkey-patch propagation)npm run buildinweb/— builds clean, source maps upload to Sentry whenSENTRY_AUTH_TOKENis set in CIPre-existing failures
5 tests in
packages/deepctl-core/tests/unit/test_base.py::TestBaseCommand::test_output_result_*fail on this branch and on baremain. Not introduced here.Related
telemetry.dx.deepgram.comcli.deepgram.comalready created (id 7211778), sits disabled until on-demand seat budget is approved